package com.nineclock.auth.intergration.aop;

import com.nineclock.auth.intergration.entity.IntergrationAuthenticationEntity;
import com.nineclock.auth.intergration.entity.NcOauthTokenDTO;
import com.nineclock.auth.intergration.threadlocal.IntergrationAuthenticationHolder;
import com.nineclock.auth.intergration.threadlocal.UserHolder;
import com.nineclock.common.entity.Result;
import com.nineclock.common.entity.UserInfo;
import com.nineclock.common.enums.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;


@Component
@Aspect
@Slf4j
public class AuthTokenAspect {

    /**
     * 环绕通过, 拦截 TokenEndPoint 中申请令牌的方法
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")//切入点表达式
    public Object postHandleAuthTokenResult(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("进入的AOP切换, 拦截申请令牌方法 ....");

        Object result = null;
        Result res = null;
        try {
            //获取请求参数 -------> spring提供
            HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getRequest();

            String authType = request.getParameter("auth_type");
            Map<String, String[]> parameterMap = request.getParameterMap();

            //组装认证实体对象
            IntergrationAuthenticationEntity authenticationEntity = new IntergrationAuthenticationEntity();
            authenticationEntity.setAuthType(authType);
            authenticationEntity.setAuthParameters(parameterMap);

            //存储ThreadLocal
            IntergrationAuthenticationHolder.set(authenticationEntity);






            //放行 ---> 执行原始方法
            result = proceedingJoinPoint.proceed();





            //-------------------------- 环绕后增强 ----> 封装统一返回的结果
            ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>)result;

            if(responseEntity != null){
                OAuth2AccessToken auth2AccessToken = responseEntity.getBody();
                UserInfo userInfo = UserHolder.get();

                //成功, 组装令牌
                if(responseEntity.getStatusCode().is2xxSuccessful()){
                    NcOauthTokenDTO oauthTokenDTO = new NcOauthTokenDTO();
                    oauthTokenDTO.setUser(userInfo);
                    oauthTokenDTO.setOauth2AccessToken(auth2AccessToken);

                    res = Result.success(oauthTokenDTO);
                }else{
                    res = Result.errorMessage(ResponseEnum.INVALID_USERNAME_PASSWORD.getMessage());
                }
            }

        } finally {
            //释放ThreadLocal中存储的认证实体信息
            IntergrationAuthenticationHolder.remove();
            UserHolder.remove();
        }


        //返回
        return ResponseEntity.ok(res);
    }

}
